package com.sansecy.pagesnaprecyclerview;

import android.content.Context;
import android.graphics.Rect;
import android.support.annotation.NonNull;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.PagerSnapHelper;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;


public class GalleryLayoutManager1 extends LinearLayoutManager {
    private static final String TAG = "GalleryLayoutManager";

    private PagerSnapHelper mPagerSnapHelper;
    private OnViewPagerListener mOnViewPagerListener;
    private OnScrollListener mOnScrollListener;
    private RecyclerView mRecyclerView;
    private int mDrift;//位移，用来判断移动方向

    private int totalWidth;
    private int scrollOffset;
    private SparseArray<Rect> allRects;
    private int widthLevel = 30;
    private float widthLevelF = (float) 0.3;
    private float widthRatioF;  //实际根据item的个数，动态调整，和widthLevelF 决定

    private float scaleLevel = 29f;
    private boolean fullWhenSingle = false;

    private int lastSelectedPage = -1;      //上一次被选中的页面

    private boolean itemAutoMargin = true;  //自动适应margin值
    private float autoMarginRatioF = 0.1F;

    public GalleryLayoutManager1(Context context, int orientation) {
        super(context, orientation, false);
        init();
    }

    public GalleryLayoutManager1(Context context, int orientation, boolean reverseLayout) {
        super(context, orientation, reverseLayout);
        init();
    }

    private void init() {
        mPagerSnapHelper = new PagerSnapHelper();
        allRects = new SparseArray<>();
    }

    /**
     * 设置当只有一个item的时候，撑满屏幕
     *
     * @param full flag
     */
    public void setFullWhenSingle(boolean full) {
        fullWhenSingle = full;
    }

    /**
     * 设置卡片的宽度等级，值越小，卡片越宽
     *
     * @param level 大于0的level值
     */
    public void setWidthLevel(int level) {
        if (level <= 0) {
            return;
        }

        widthLevel = level;
        widthLevelF = widthLevel / 100f;
        widthRatioF = widthLevelF;
    }

    public void setItemAutoMargin(boolean autoMargin) {
        this.itemAutoMargin = autoMargin;
        if (itemAutoMargin) {
            autoMarginRatioF = 0.1F;
        } else {
            autoMarginRatioF = 0.001F;
        }
    }

    /**
     * 获取宽度等级
     *
     * @return 获取当前的宽度等级
     */
    public int getWidthLevel() {
        return widthLevel;
    }

    /**
     * 设置两边卡片的缩放比列
     *
     * @param scale 缩放比列
     */
    public void setScaleLevel(float scale) {
        if (scale <= 0) {
            return;
        }

        scaleLevel = scale;
    }

    /**
     * 两侧卡片的缩放等级
     *
     * @return scaleLevel
     */
    public float getScaleLevel() {
        return scaleLevel;
    }

    @Override
    public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
        if (getItemCount() == 1) {       //防止一张卡片的时候抖动
            scrollOffset = 0;
        }
        //滑动的时候调用，控制滑动距离
        if (scrollOffset + dx < 0) {
            dx = -scrollOffset;
        } else if (scrollOffset + dx > totalWidth - getWidth()) {
            dx = totalWidth - getWidth() - scrollOffset;
        }
        offsetChildrenHorizontal(-dx);
        recyclerAndFillView(recycler, state);
        scrollOffset += dx;

        if (mOnScrollListener != null) {
            mOnScrollListener.onScroll(scrollOffset);       //每次滑动一张卡片的距离
        }
        return dx;
    }

    @Override
    public void onAttachedToWindow(RecyclerView view) {
        super.onAttachedToWindow(view);

        mPagerSnapHelper.attachToRecyclerView(view);
        this.mRecyclerView = view;
        mRecyclerView.addOnChildAttachStateChangeListener(mChildAttachStateChangeListener);
    }


    /**
     * 滑动状态的改变
     * 缓慢拖拽-> SCROLL_STATE_DRAGGING
     * 快速滚动-> SCROLL_STATE_SETTLING
     * 空闲状态-> SCROLL_STATE_IDLE
     *
     * @param state 状态
     */
    @Override
    public void onScrollStateChanged(int state) {
        switch (state) {
            case RecyclerView.SCROLL_STATE_IDLE:
                View viewIdle = mPagerSnapHelper.findSnapView(this);
                if (viewIdle != null) {
                    int positionIdle = getPosition(viewIdle);

                    if (mOnScrollListener != null && lastSelectedPage != positionIdle) {
                        mOnScrollListener.onPageSelected(positionIdle);
                        lastSelectedPage = positionIdle;
                    }
                }
                break;
            case RecyclerView.SCROLL_STATE_DRAGGING:
                break;
            case RecyclerView.SCROLL_STATE_SETTLING:
                break;
            default:
                break;
        }
    }


    /**
     * 监听竖直方向的相对偏移量
     *
     * @param dy       y轴偏移量
     * @param recycler recyclerview
     * @param state    状态
     * @return 偏移量
     */
    @Override
    public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
        this.mDrift = dy;
        return super.scrollVerticallyBy(dy, recycler, state);
    }


//    /**
//     * 监听水平方向的相对偏移量，快速翻页
//     *
//     * @param dx
//     * @param recycler
//     * @param state
//     * @return
//     */
//    @Override
//    public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
//        this.mDrift = dx;
//        return super.scrollHorizontallyBy(dx, recycler, state);
//    }

    /**
     * if return >= 0 snap is exist
     * if return < 0 snap is not exist
     *
     * @return 是否找到snap位置
     */
    public int findSnapPosition() {
        View viewIdle = mPagerSnapHelper.findSnapView(this);
        if (viewIdle != null) {
            return getPosition(viewIdle);
        } else {
            return -1;
        }
    }

    /**
     * 设置监听
     *
     * @param listener 监听器
     */
    public void setOnViewPagerListener(OnViewPagerListener listener) {
        this.mOnViewPagerListener = listener;
    }

    public void setOnScrollListener(OnScrollListener listener) {
        this.mOnScrollListener = listener;
    }

    private RecyclerView.OnChildAttachStateChangeListener mChildAttachStateChangeListener = new RecyclerView.OnChildAttachStateChangeListener() {
        @Override
        public void onChildViewAttachedToWindow(@NonNull View view) {
            if (mOnViewPagerListener != null && getChildCount() == 1) {
                mOnViewPagerListener.onInitComplete();
            }
        }

        @Override
        public void onChildViewDetachedFromWindow(@NonNull View view) {
            if (mOnViewPagerListener != null) {
                if (mDrift >= 0) {
                    mOnViewPagerListener.onPageRelease(true, getPosition(view));
                } else {
                    mOnViewPagerListener.onPageRelease(false, getPosition(view));
                }
            }

        }
    };

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        super.onLayoutChildren(recycler, state);
        calculateChildrenSize(recycler);
        recyclerAndFillView(recycler, state);
    }

    /**
     * 计算每个子item的尺寸
     *
     * @param recycler recyclerview
     */
    private void calculateChildrenSize(RecyclerView.Recycler recycler) {

        if (getItemCount() == 1 && fullWhenSingle) {
            widthRatioF = 0.1F;
        } else {
            widthRatioF = widthLevelF;
        }

        //改变系数，可以改变初始页面的第一个item的状态，初始状态要留空白，所以totalWidth加上的是第一张卡片左边的空白
        totalWidth = (int) (getWidth() * widthRatioF / 2);

        for (int i = 0; i < getItemCount(); i++) {
            View v = recycler.getViewForPosition(i);
            addView(v);
            //getWidth的系数控制每个item的宽度，系数越大，item宽度小,整个layout的宽度
            //getHeight的系数控制每个item的高度，系数越大，item高度越小，整个layout的高度
            measureChildWithMargins(v, (int) (getWidth() * widthRatioF), (int) (getHeight() * autoMarginRatioF));
            calculateItemDecorationsForChild(v, new Rect());
            int width = getDecoratedMeasuredWidth(v);
            int height = getDecoratedMeasuredHeight(v);
            Rect childRect = allRects.get(i);
            if (null == childRect) {
                childRect = new Rect();
            }
            //通过系数可以调节位置高度
            childRect.set(totalWidth, (getHeight() - height) / 2, totalWidth + width, (getHeight() + height) / 2);
            totalWidth += width;
            allRects.put(i, childRect);
        }
        totalWidth += getWidth() * widthRatioF / 2;       //最后一张卡片后面的空白
    }

    private void recyclerAndFillView(RecyclerView.Recycler recycler, RecyclerView.State state) {
        if (getItemCount() == 0 || state.isPreLayout()) return;
        int w = getWidth();
        int h = getHeight();
        detachAndScrapAttachedViews(recycler);
        Rect displayRect = new Rect(scrollOffset, 0, scrollOffset + w, h);

        float scale;
        for (int i = 0; i < getItemCount(); i++) {
            if (Rect.intersects(displayRect, allRects.get(i))) {
                View v = recycler.getViewForPosition(i);
                measureChildWithMargins(v, (int) (getWidth() * widthRatioF), (int) (getHeight() * 0.1));
                addView(v);

                Rect rect = allRects.get(i);
                scale = (float) (rect.left + getWidth() * 0.35 - getWidth() * 0.5 - scrollOffset);
                scale /= translate();
                scale = Math.abs(scale);
                v.setAlpha(1 - scale * 0.5f);
                scale *= 2 / scaleLevel;
                scale = 1 - scale;
                v.setScaleX(scale);         //设置缩放比列，当前的页面比例为1，两边的比列为0.77 左右。1080P屏幕
                v.setScaleY(scale);
                layoutDecorated(v, rect.left - scrollOffset, rect.top, rect.right - scrollOffset, rect.bottom);
            }
        }
    }

    private float translate() {
        return (float) (getWidth() * 0.7);
    }

    public interface OnScrollListener {
        /**
         * 滑动过程中的监听器
         *
         * @param dx 当前滑动的距离
         */
        void onScroll(int dx);

        /**
         * 当页面被选中的listener
         *
         * @param position 第几个页面被选中
         */
        void onPageSelected(int position);
    }

    public interface OnViewPagerListener {


        /**
         * 初始化第一个View
         */
        void onInitComplete();


        /**
         * 释放的监听
         *
         * @param isNext   是否是下一个
         * @param position 位置
         */
        void onPageRelease(boolean isNext, int position);
    }
}
